﻿using Comm100.Framework.Domain.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Bot.Domain.Entities;
using Bot.Domain.Interfaces;
using Bot.Domain.Bo;
using Castle.Windsor;
using Bot.Domain.Specifications;
using AutoMapper;

namespace Bot.Domain.Categories.Service
{
    public class IntentAnswerInChannelDomainService : IIntentAnswerInChannelDomainService
    {
        private IWindsorContainer _container;
        private readonly IRepository<Guid, IntentAnswerInChannel> _repository;
        public IMapper Mapper { get; set; }

        public IntentAnswerInChannelDomainService(IRepository<Guid, IntentAnswerInChannel> repository, IWindsorContainer container)
        {
            this._repository = repository;
            this._container = container;
        }

        public IntentAnswerInChannel Create(IntentAnswerInChannel answerInChannel)
        {
            if(answerInChannel.Id == Guid.Empty)
            {
                answerInChannel.Id = Guid.NewGuid();
            }           
            if (answerInChannel.AuthenticationRequest != null)
            {
                IAnswerInChannelAuthenticationRequestDomainService answerInChannelAuthenticationRequestDomainService = _container.Resolve<IAnswerInChannelAuthenticationRequestDomainService>();
                answerInChannel.AuthenticationRequest.Id = Guid.NewGuid();
                answerInChannelAuthenticationRequestDomainService.Create(answerInChannel.AuthenticationRequest);
                answerInChannel.AuthenticationRequestId = answerInChannel.AuthenticationRequest.Id;
            }
            if (answerInChannel.LocationRequest != null)
            {
                IAnswerInChannelLocationRequestDomainService answerInChannelLocationRequestDomainService = _container.Resolve<IAnswerInChannelLocationRequestDomainService>();
                answerInChannel.LocationRequest.Id = Guid.NewGuid();
                answerInChannelLocationRequestDomainService.Create(answerInChannel.LocationRequest);
                answerInChannel.LocationRequestId = answerInChannel.LocationRequest.Id;
            }
            if (answerInChannel.Form != null)
            {
                IAnswerInChannelFormDomainService answerInChannelFormDomainService = _container.Resolve<IAnswerInChannelFormDomainService>();
                answerInChannel.Form.Id = Guid.NewGuid();
                answerInChannelFormDomainService.Create(answerInChannel.Form);
                answerInChannel.FormId = answerInChannel.Form.Id;
            }
            if(answerInChannel.Prompts!=null&& answerInChannel.Prompts.Count > 0)
            {
                IAnswerInChannelPromptDomainService answerInChannelPromptDomainService = _container.Resolve<IAnswerInChannelPromptDomainService>();
                foreach(var prompt in answerInChannel.Prompts)
                {
                    prompt.AnswerInChannelId = answerInChannel.Id;
                    prompt.Id = Guid.NewGuid();
                    answerInChannelPromptDomainService.Create(prompt);
                }
            }
            if (answerInChannel.Responses != null && answerInChannel.Responses.Count > 0)
            {
                IResponseDomainService responseDomainService = _container.Resolve<IResponseDomainService>();
                foreach (var response in answerInChannel.Responses)
                {
                    response.ParentId = answerInChannel.Id;
                    response.Id = Guid.NewGuid();
                    responseDomainService.Create(response);
                }
            }
            return _repository.Create(answerInChannel);
        }

        public IntentAnswerInChannel Get(Guid id, string include="")
        {
            var intentAnswerInChannel = _repository.Get(id);
            if (intentAnswerInChannel != null
                && !string.IsNullOrEmpty(include))
            {
                IResponseDomainService responseDomainService = _container.Resolve<IResponseDomainService>();
                IAnswerInChannelAuthenticationRequestDomainService answerInChannelAuthenticationRequestDomainService = _container.Resolve<IAnswerInChannelAuthenticationRequestDomainService>();
                IAnswerInChannelLocationRequestDomainService answerInChannelLocationRequestDomainService = _container.Resolve<IAnswerInChannelLocationRequestDomainService>();
                IAnswerInChannelFormDomainService answerInChannelFormDomainService = _container.Resolve<IAnswerInChannelFormDomainService>();
                IAnswerInChannelPromptDomainService answerInChannelPromptDomainService = _container.Resolve<IAnswerInChannelPromptDomainService>();

                if (include.Split(',').Contains("responses"))
                {
                    intentAnswerInChannel.Responses = responseDomainService.GetByParentId(intentAnswerInChannel.Id).ToList();
                }
                if (include.Split(',').Contains("authenticationRequest") && intentAnswerInChannel.AuthenticationRequestId.HasValue && intentAnswerInChannel.AuthenticationRequestId != Guid.Empty)
                {
                    intentAnswerInChannel.AuthenticationRequest = answerInChannelAuthenticationRequestDomainService.Get(intentAnswerInChannel.AuthenticationRequestId.Value);
                }
                if (include.Split(',').Contains("locationRequest") && intentAnswerInChannel.LocationRequestId.HasValue && intentAnswerInChannel.LocationRequestId != Guid.Empty)
                {
                    intentAnswerInChannel.LocationRequest = answerInChannelLocationRequestDomainService.Get(intentAnswerInChannel.LocationRequestId.Value);
                }
                if (include.Split(',').Contains("form") && intentAnswerInChannel.FormId.HasValue && intentAnswerInChannel.FormId != Guid.Empty)
                {
                    intentAnswerInChannel.Form = answerInChannelFormDomainService.Get(intentAnswerInChannel.FormId.Value);
                }
                if (include.Split(',').Contains("prompts"))
                {
                    intentAnswerInChannel.Prompts = answerInChannelPromptDomainService.GetByAnswerInChannelId(intentAnswerInChannel.Id, include).ToList();
                }
            }
            return intentAnswerInChannel;
        }

        public IntentAnswerInChannel Update(IntentAnswerInChannelUpdateBo bo)
        {
            IntentAnswerInChannel intentAnswerInChannel = _repository.Get(bo.Id);

            IAnswerInChannelAuthenticationRequestDomainService answerInChannelAuthenticationRequestDomainService = _container.Resolve<IAnswerInChannelAuthenticationRequestDomainService>();
            IAnswerInChannelLocationRequestDomainService answerInChannelLocationRequestDomainService = _container.Resolve<IAnswerInChannelLocationRequestDomainService>();
            IAnswerInChannelFormDomainService answerInChannelFormDomainService = _container.Resolve<IAnswerInChannelFormDomainService>();
            IAnswerInChannelPromptDomainService answerInChannelPromptDomainService = _container.Resolve<IAnswerInChannelPromptDomainService>();
            IResponseDomainService responseDomainService = _container.Resolve<IResponseDomainService>();

            if (bo.AuthenticationRequest != null)
            {
                if(bo.AuthenticationRequest.Id == Guid.Empty)
                {
                    bo.AuthenticationRequest.Id = Guid.NewGuid();
                    bo.AuthenticationRequestId = bo.AuthenticationRequest.Id;
                    var authenticationRequest = Mapper.Map<AnswerInChannelAuthenticationRequest>(bo.AuthenticationRequest);
                    answerInChannelAuthenticationRequestDomainService.Create(authenticationRequest);
                }
                else
                {
                    answerInChannelAuthenticationRequestDomainService.Update(bo.AuthenticationRequest);
                }
            }
            //删除原来的
            if(intentAnswerInChannel.AuthenticationRequestId.HasValue
                && intentAnswerInChannel.AuthenticationRequestId!=Guid.Empty
                && (bo.AuthenticationRequest == null || intentAnswerInChannel.AuthenticationRequestId != bo.AuthenticationRequest.Id))
            {
                answerInChannelAuthenticationRequestDomainService.Delete(intentAnswerInChannel.AuthenticationRequestId.Value);
            }

            if (bo.LocationRequest != null)
            {
                if(bo.LocationRequest.Id == Guid.Empty)
                {
                    bo.LocationRequest.Id = Guid.NewGuid();
                    bo.LocationRequestId = bo.LocationRequest.Id;
                    var locationRequest = Mapper.Map<AnswerInChannelLocationRequest>(bo.LocationRequest);
                    answerInChannelLocationRequestDomainService.Create(locationRequest);
                }
                else
                {
                    answerInChannelLocationRequestDomainService.Update(bo.LocationRequest);
                }                    
            }
            //删除原来的
            if (intentAnswerInChannel.LocationRequestId.HasValue
                && intentAnswerInChannel.LocationRequestId != Guid.Empty
                && (bo.LocationRequest == null || intentAnswerInChannel.LocationRequestId != bo.LocationRequest.Id))
            {
                answerInChannelLocationRequestDomainService.Delete(intentAnswerInChannel.LocationRequestId.Value);
            }

            if (bo.Form != null)
            {
                if (bo.Form.Id == Guid.Empty)
                {
                    bo.Form.Id = Guid.NewGuid();
                    bo.FormId = bo.Form.Id;
                    var form = Mapper.Map<AnswerInChannelForm>(bo.Form);
                    answerInChannelFormDomainService.Create(form);
                }
                else
                {
                    answerInChannelFormDomainService.Update(bo.Form);
                }
            }
            //删除原来的
            if (intentAnswerInChannel.FormId.HasValue
                && intentAnswerInChannel.FormId != Guid.Empty
                && (bo.Form == null || intentAnswerInChannel.FormId != bo.Form.Id) )
            {
                answerInChannelFormDomainService.Delete(intentAnswerInChannel.FormId.Value);
            }

            var promptIds = new List<Guid> { };
            if (bo.Prompts != null && bo.Prompts.Count > 0)
            {
                foreach (var promptBo in bo.Prompts)
                {
                    if(promptBo.Id == Guid.Empty)
                    {
                        promptBo.Id = Guid.NewGuid();
                        promptBo.AnswerInChannelId = bo.Id;
                        var prompt = Mapper.Map<AnswerInChannelPrompt>(promptBo);
                        answerInChannelPromptDomainService.Create(prompt);
                        promptIds.Add(promptBo.Id);
                    }
                    else
                    {
                        promptBo.AnswerInChannelId = bo.Id;
                        answerInChannelPromptDomainService.Update(promptBo);
                        promptIds.Add(promptBo.Id);
                    }
                }
            }
            //删除原来的
            var prompts = answerInChannelPromptDomainService.GetByAnswerInChannelId(bo.Id);
            foreach(var prompt in prompts)
            {
                if (!promptIds.Contains(prompt.Id))
                {
                    answerInChannelPromptDomainService.Delete(prompt.Id);
                }
            }

            var responseIds = new List<Guid> { };
            if (bo.Responses != null && bo.Responses.Count > 0)
            {         
                foreach (var responseBo in bo.Responses)
                {
                    if(responseBo.Id == Guid.Empty)
                    {
                        responseBo.Id = Guid.NewGuid();
                        responseBo.ParentId = bo.Id;
                        var response = Mapper.Map<Response>(responseBo);
                        responseDomainService.Create(response);
                        responseIds.Add(responseBo.Id);
                    }
                    else
                    {
                        responseBo.ParentId = bo.Id;
                        responseDomainService.Update(responseBo);
                        responseIds.Add(responseBo.Id);
                    }
      
                }
            }
            //删除原来的
            var responses = responseDomainService.GetByParentId(bo.Id);
            foreach (var response in responses)
            {
                if (!responseIds.Contains(response.Id))
                {
                    responseDomainService.Delete(response.Id);
                }
            }

            intentAnswerInChannel.Id = bo.Id;
            intentAnswerInChannel.IntentId = bo.IntentId;
            intentAnswerInChannel.Channel = bo.Channel;
            intentAnswerInChannel.LocationRequestId = bo.LocationRequestId;
            intentAnswerInChannel.InformationCollectionType = bo.InformationCollectionType;
            intentAnswerInChannel.FormId = bo.FormId;
            intentAnswerInChannel.AuthenticationRequestId = bo.AuthenticationRequestId;

            _repository.Update(intentAnswerInChannel);

            return intentAnswerInChannel;

        }

        public void UpdateForAuthenticationRequestId(Guid intentAnswerInChannelId, Guid authenticationRequestId)
        {
            var intentAnswerInChannel = Get(intentAnswerInChannelId);
            intentAnswerInChannel.AuthenticationRequestId = authenticationRequestId;
            _repository.Update(intentAnswerInChannel);            
        }
        public void UpdateForFormId(Guid intentAnswerInChannelId, Guid formId)
        {
            var intentAnswerInChannel = Get(intentAnswerInChannelId);
            intentAnswerInChannel.FormId = formId;
            _repository.Update(intentAnswerInChannel);
        }
        public void UpdateForLocationRequestId(Guid intentAnswerInChannelId, Guid locationRequestId)
        {
            var intentAnswerInChannel = Get(intentAnswerInChannelId);
            intentAnswerInChannel.LocationRequestId = locationRequestId;
            _repository.Update(intentAnswerInChannel);
        }
        public IntentAnswerInChannel GetByAuthenticationRequestId(Guid authenticationRequestId)
        {
            var intentAnswerInChannel = _repository.List(new IntentAnswerInChannelFilterSpecification("", authenticationRequestId)).FirstOrDefault();
            return intentAnswerInChannel;
        }
        public IntentAnswerInChannel GetByFormId(Guid formId)
        {
            var intentAnswerInChannel = _repository.List(new IntentAnswerInChannelFilterSpecification("","", formId)).FirstOrDefault();
            return intentAnswerInChannel;
        }
        public IntentAnswerInChannel GetByLocationRequestId(Guid locationRequestId)
        {
            var intentAnswerInChannel = _repository.List(new IntentAnswerInChannelFilterSpecification("", "","", locationRequestId)).FirstOrDefault();
            return intentAnswerInChannel;
        }

        public IEnumerable<IntentAnswerInChannel> List()
        {
            return _repository.ListAll();
        }

        public void Delete(Guid id)
        {
            IntentAnswerInChannel intentAnswerInChannel = Get(id, "responses,authenticationRequest,locationRequest,form,prompts");
            if (intentAnswerInChannel != null)
            {
                IResponseDomainService responseDomainService = _container.Resolve<IResponseDomainService>();
                IAnswerInChannelAuthenticationRequestDomainService answerInChannelAuthenticationRequestDomainService = _container.Resolve<IAnswerInChannelAuthenticationRequestDomainService>();
                IAnswerInChannelLocationRequestDomainService answerInChannelLocationRequestDomainService = _container.Resolve<IAnswerInChannelLocationRequestDomainService>();
                IAnswerInChannelFormDomainService answerInChannelFormDomainService = _container.Resolve<IAnswerInChannelFormDomainService>();
                IAnswerInChannelPromptDomainService answerInChannelPromptDomainService = _container.Resolve<IAnswerInChannelPromptDomainService>();

                if (intentAnswerInChannel.Responses!=null)
                {
                    foreach(var response in intentAnswerInChannel.Responses)
                    {
                        responseDomainService.Delete(response.Id);
                    }                    
                }
                if (intentAnswerInChannel.AuthenticationRequest != null)
                {
                    answerInChannelAuthenticationRequestDomainService.Delete(intentAnswerInChannel.AuthenticationRequest.Id);
                }
                if (intentAnswerInChannel.LocationRequest != null)
                {
                    answerInChannelLocationRequestDomainService.Delete(intentAnswerInChannel.LocationRequest.Id);
                }
                if (intentAnswerInChannel.Form != null)
                {
                    answerInChannelFormDomainService.Delete(intentAnswerInChannel.Form.Id);
                }
                if (intentAnswerInChannel.Prompts != null)
                {
                    foreach (var prompt in intentAnswerInChannel.Prompts)
                    {
                        answerInChannelPromptDomainService.Delete(prompt.Id);
                    }
                }
            }
            _repository.Delete(intentAnswerInChannel);

        }

        public IEnumerable<IntentAnswerInChannel> GetByIntentId(Guid intentId, string include = "")
        {
            var list = _repository.List(new IntentAnswerInChannelFilterSpecification(intentId)).ToList();

            if (list != null && list.Count > 0 && !string.IsNullOrEmpty(include))
            {
                IResponseDomainService responseDomainService = _container.Resolve<IResponseDomainService>();
                IAnswerInChannelAuthenticationRequestDomainService answerInChannelAuthenticationRequestDomainService = _container.Resolve<IAnswerInChannelAuthenticationRequestDomainService>();
                IAnswerInChannelLocationRequestDomainService answerInChannelLocationRequestDomainService = _container.Resolve<IAnswerInChannelLocationRequestDomainService>();
                IAnswerInChannelFormDomainService answerInChannelFormDomainService = _container.Resolve<IAnswerInChannelFormDomainService>();
                IAnswerInChannelPromptDomainService answerInChannelPromptDomainService = _container.Resolve<IAnswerInChannelPromptDomainService>();
                foreach (var item in list)
                {
                    if (include.Split(',').Contains("responses"))
                    {                        
                        item.Responses = responseDomainService.GetByParentId(item.Id,include).ToList();
                    }
                    if (include.Split(',').Contains("authenticationRequest")&&item.AuthenticationRequestId.HasValue&& item.AuthenticationRequestId!=Guid.Empty)
                    {                        
                        item.AuthenticationRequest = answerInChannelAuthenticationRequestDomainService.Get(item.AuthenticationRequestId.Value);
                    }
                    if (include.Split(',').Contains("locationRequest") && item.LocationRequestId.HasValue && item.LocationRequestId != Guid.Empty)
                    {
                        item.LocationRequest = answerInChannelLocationRequestDomainService.Get(item.LocationRequestId.Value);
                    }
                    if (include.Split(',').Contains("form") && item.FormId.HasValue && item.FormId != Guid.Empty)
                    {
                        item.Form = answerInChannelFormDomainService.Get(item.FormId.Value, include);
                    }
                    if (include.Split(',').Contains("prompts"))
                    {
                        item.Prompts = answerInChannelPromptDomainService.GetByAnswerInChannelId(item.Id, include).ToList();
                    }
                }
            }

            return list;
        }
        public IntentAnswerInChannel GetByIntentIdAndChannel(Guid intentId, string channel)
        {
            var list = _repository.List(new IntentAnswerInChannelFilterSpecification(intentId,channel)).ToList();
            return list?.FirstOrDefault();
        }
    }
}
